---
title: Wallet Standard
description: The Wallet Standard defines how dApps can automatically discover and interact with wallets.
keywords: [ mysten/wallet-standard, wallet standards, Wallet Standard, browser extensions, exposing accounts, wallet events, register in window, wallet best practices, efficient transaction execution, wallet data, managing wallets, wallet-standard ]
pagination_prev: null
---

Browser extension wallets built for Sui use the [Wallet Standard](https://github.com/wallet-standard/wallet-standard/). This is a cross-chain standard that defines how dApps can automatically discover and interact with wallets.

If you are building a wallet, the helper library `@mysten/wallet-standard` provides types and utilities to help get started.

## Working with wallets

The Wallet Standard includes features to help build wallets.

### Creating a wallet interface

Create a class that represents your wallet. Use the `Wallet` interface from
`@mysten/wallet-standard` to help ensure your class adheres to the standard.

```tsx
import { SUI_DEVNET_CHAIN, Wallet } from '@mysten/wallet-standard';

class YourWallet implements Wallet {
	get version() {
		// Return the version of the Wallet Standard this implements (in this case, 1.0.0).
		return '1.0.0';
	}

	get name() {
		return 'Wallet Name';
	}

	get icon() {
		return 'some-icon-data-url';
	}

	// Return the Sui chains that your wallet supports.
	get chains() {
		return [SUI_DEVNET_CHAIN];
	}
}
```

### Implementing features

Features are standard methods consumers can use to interact with a wallet. Wallets should implement the following features:

**Core features**
- `standard:connect` - Use to prompt the wallet for account authorization.
- `standard:events` - Use to listen for changes that happen within the wallet, such as accounts
  being added or removed.

**Transaction features**

Libraries built on top of the Wallet Standard (like dApp Kit) require transaction signing capabilities. Implement both current and legacy methods for maximum compatibility:

Current methods:
- `sui:signTransaction` - Use to prompt the user to sign a transaction and return the serialized
  transaction and signature back to the dApp. This method does not submit the transaction for
  execution.
- `sui:signAndExecuteTransaction` - Use to prompt the user to sign a transaction, then submit it
  for execution to the blockchain.

Legacy methods:
- `sui:signTransactionBlock` - The legacy version of `sui:signTransaction`. Many existing dApps still rely on this method.
- `sui:signAndExecuteTransactionBlock` - The legacy version of `sui:signAndExecuteTransaction`. Many existing dApps still rely on this method.

**Personal message signing**
- `sui:signPersonalMessage` - Use to prompt the user to sign a personal message and return the
  message signature back to the dApp. This is essential for user verification flows used by many dApps.

Implement these features in your wallet class under the `features` property:

```tsx
import {
  StandardConnectFeature,
  StandardConnectMethod,
  StandardEventsFeature,
  StandardEventsOnMethod,
  SuiFeatures,
  SuiSignPersonalMessageMethod,
  SuiSignTransactionMethod,
  SuiSignAndExecuteTransactionMethod,
  StandardConnect,
  StandardEvents,
  SuiSignPersonalMessage,
  SuiSignTransaction,
  SuiSignAndExecuteTransaction
} from "@mysten/wallet-standard";

class YourWallet implements Wallet {
	/* ... existing code from above ... */

  get features(): ConnectFeature & EventsFeature & SuiFeatures {
    return {
      [StandardConnect]: {
        version: "1.0.0",
        connect: this.#connect,
      },
      [StandardEvents]: {
        version: "1.0.0",
        on: this.#on,
      },
			[SuiSignPersonalMessage]: {
        version: "1.1.0",
				signPersonalMessage: this.#signPersonalMessage,
			},
      [SuiSignTransaction]: {
        version: "2.0.0",
        signTransaction: this.#signTransaction,
      },
      [SuiSignAndExecuteTransaction]: {
        version: "2.0.0",
        signAndExecuteTransaction: this.#signAndExecuteTransaction,
      },
    };
  };

  #on: EventsOnMethod = () => {
    // Your wallet's events on implementation
  };

  #connect: ConnectMethod = () => {
    // Your wallet's connect implementation
  };

	#signPersonalMessage: SuiSignPersonalMessageMethod = () => {
    // Your wallet's signPersonalMessage implementation
  };

  #signTransaction: SuiSignTransactionMethod = () => {
    // Your wallet's signTransaction implementation
  };

  #signAndExecuteTransaction: SuiSignAndExecuteTransactionMethod = () => {
    // Your wallet's signAndExecuteTransaction implementation
  };
}
```

### Exposing accounts

The last requirement of the wallet interface is to expose an `accounts` interface. Wallets that comply with the Wallet Standard should automatically populate this array with any previously authorized accounts when the wallet loads. This means:

- On first visit: The array will be empty until the user authorizes accounts through `standard:connect`
- On subsequent visits: Previously authorized accounts automatically appear without any dApp action
- After revocation: Accounts that have been revoked won't appear in the array

The accounts use the `ReadonlyWalletAccount` class to construct an account matching the required interface.

```tsx
import { ReadonlyWalletAccount } from '@mysten/wallet-standard';

class YourWallet implements Wallet {
	get accounts() {
		// Assuming we already have some internal representation of accounts:
		return someWalletAccounts.map(
			(walletAccount) =>
				new ReadonlyWalletAccount({
					address: walletAccount.suiAddress,
					publicKey: walletAccount.pubkey,
					// The Sui chains that this account supports. This can be a subset of the wallet's supported chains.
          // These chains must exist on the wallet as well.
					chains: [SUI_DEVNET_CHAIN],
					// The features that this account supports. This can be a subset of the wallet's supported features.
					// These features must exist on the wallet as well.
					features: [
						SuiSignPersonalMessage,
            SuiSignTransaction,
						SuiSignAndExecuteTransaction,
					],
				}),
		);
	}
}
```

### Registering in the window

After you have a compatible interface for your wallet, use the `registerWallet`
function to register it.

```tsx
import { registerWallet } from '@mysten/wallet-standard';

registerWallet(new YourWallet());
```

## Managing wallets

The Wallet Standard includes features to help your apps interact with wallets.

### Wallet data

To query the installed wallets in a user's browser, use the `get` function of `getWallets`.

```tsx
import { getWallets } from '@mysten/wallet-standard';

const availableWallets = getWallets().get();
```

The return from this call (`availableWallets` in the previous code) is an array of `Wallet` types.

Use the `Wallet.icon` and `Wallet.name` attributes to display the wallet details on your web page.

The `Wallet.accounts` is an array of `WalletAccount`s. Each `WalletAccount` type has `address` and `publicKey` properties, which are most useful during development. This data fills and caches after account authorization.

### Features

Both the `Wallet` type and the `WalletAccount` type have a property called `features`. The main wallet functionality is found here. The mandatory features that wallets must implement are listed in the previous code.

Many wallets choose to omit some non-mandatory features or add some custom features, so be sure to check the relevant wallet documentation if you intend to integrate a specific wallet.

### Authorizing wallet accounts

The Wallet Standard uses a persistent authorization model. Despite the "connect" terminology in the API, wallets should automatically restore previously authorized accounts when they load, without any action from the dApp. The `connect()` method is specifically for prompting users to authorize accounts when needed.

**How account authorization works:**

1. **Wallets restore accounts automatically**: When a wallet loads, it should automatically populate its `accounts` array with any previously authorized accounts for the current dApp. This happens without any dApp interaction.

2. **Only prompt when necessary**: Call `connect()` only when:
   - The `accounts` array is empty (first-time user or all accounts were revoked)
   - The current accounts don't meet your requirements (e.g., you need an account on a specific chain)
   - The user explicitly wants to authorize more accounts

```tsx
await wallet.features['standard:connect'].connect();
```

:::info

The `connect()` method has a `silent` parameter that is intended to retrieve previously authorized accounts without user interaction, but this parameter is planned for deprecation in future versions of the Wallet Standard. Wallets should instead automatically populate the `accounts` array on load.

:::

When you do call `connect()`, the wallet will open a pop-up for the user to select and authorize which accounts the dApp can access.

### Revoking account authorization

Similar to the connect (account authorization) feature, the Wallet Standard also includes `standard:disconnect` to revoke a dApp's access to wallet accounts. The following example calls this feature:

```tsx
wallet.features['standard:disconnect'].disconnect();
```

### Transactions - suggested approach

Once the user has authorized accounts from a wallet, your app has the necessary information to execute transactions, such as address and method.

Construct the transaction separately with the `@mysten/sui` library and then sign it with the private key of the user. Use the `sui:signTransaction` feature to achieve this:

```tsx
wallet.features['sui:signTransaction'].signTransaction({
  transaction: <Transaction>,
  account: <WalletAccount>
})
```

Similar to account authorization, this process opens a pop-up dialog for the user to either accept or decline the transaction. Upon accepting, the function returns an object in the form `{bytes: String, signature: Uint8Array}`. The `bytes` value is the `b64` encoding of the transaction and the `signature` value is the transaction signature.

To execute the transaction, use `SuiClient` from `@mysten/sui`:

```tsx
const client: SuiClient
client.executeTransactionBlock({
    transactionBlock: bytes,
    signature: signature,
    options: {}
})
```

### Transactions - abbreviated approach

Many wallets abstract the above flow into one feature: `sui:signAndExecuteTransaction`. The required arguments for this feature are the raw transaction and the options with the desired information to be included in the response:

- `showEffects`: Include the transaction effects.
- `showEvents`: Include the transaction events.
- `showObjectChanges`: Include all the objects that were deleted, created, or mutated.
- `showBalanceChanges`: Include any coin transfer that took place.
- `showInput`: Include the transaction's input.
- `showRawInput`: Same as `showInput` but the format is raw.

### Events wallets emit

The wallet emits events on certain user actions that apps can listen to. These events allow your app to be responsive to user actions on their wallets.

The Wallet Standard only defines the change event that can apply to chains, features, or accounts.

- `chains`: A change event on the chains means the user switched the wallet's active network, such as from Devnet to Testnet.
- `features`: The user added or removed permission for your app to access certain wallet features.
- `accounts`: The user added or removed an account (address) to interact with your app.

To subscribe your apps to events with the following call:

```tsx
const unsubscribe = wallet.features['standard:events'].on('change', callback);
```

This call returns a function that can be called to unsubscribe from listening to the events.

The callback is the handler that contains the logic to perform when the event fires. The input to the callback function is an object with the following type:

```tsx
{
    accounts: WalletAccount[],
    chains: IdentifierArray,
    features: IdentifierRecord<unknown>
}
```

These values are all arrays containing the new or changed items. Consequently, every event populates only one array in most cases, the rest are empty.

### Implementation example

Mysten Labs offers a bare bones scaffold for React-based applications called `@mysten/dapp-kit`. See the [dApp Kit documentation](https://sdk.mystenlabs.com/dapp-kit) for more information.
